//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension DSQL {
    // MARK: Enums

    public enum ClusterStatus: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "ACTIVE"
        case creating = "CREATING"
        case deleted = "DELETED"
        case deleting = "DELETING"
        case failed = "FAILED"
        case idle = "IDLE"
        case inactive = "INACTIVE"
        case pendingDelete = "PENDING_DELETE"
        case pendingSetup = "PENDING_SETUP"
        case updating = "UPDATING"
        public var description: String { return self.rawValue }
    }

    public enum EncryptionStatus: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case enabled = "ENABLED"
        case enabling = "ENABLING"
        case kmsKeyInaccessible = "KMS_KEY_INACCESSIBLE"
        case updating = "UPDATING"
        public var description: String { return self.rawValue }
    }

    public enum EncryptionType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case awsOwnedKmsKey = "AWS_OWNED_KMS_KEY"
        case customerManagedKmsKey = "CUSTOMER_MANAGED_KMS_KEY"
        public var description: String { return self.rawValue }
    }

    public enum ValidationExceptionReason: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case cannotParse = "cannotParse"
        case deletionProtectionEnabled = "deletionProtectionEnabled"
        case fieldValidationFailed = "fieldValidationFailed"
        case other = "other"
        case unknownOperation = "unknownOperation"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct ClusterSummary: AWSDecodableShape {
        /// The ARN of the cluster.
        public let arn: String
        /// The ID of the cluster.
        public let identifier: String

        @inlinable
        public init(arn: String, identifier: String) {
            self.arn = arn
            self.identifier = identifier
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
            case identifier = "identifier"
        }
    }

    public struct ConflictException: AWSErrorShape {
        public let message: String
        /// Resource Id
        public let resourceId: String?
        /// Resource Type
        public let resourceType: String?

        @inlinable
        public init(message: String, resourceId: String? = nil, resourceType: String? = nil) {
            self.message = message
            self.resourceId = resourceId
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case resourceId = "resourceId"
            case resourceType = "resourceType"
        }
    }

    public struct CreateClusterInput: AWSEncodableShape {
        /// A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. Idempotency ensures that an API request completes only once. With an idempotent request, if the original request completes successfully, the subsequent retries with the same client token return the result from the original successful request and they have no additional effect. If you don't specify a client token, the Amazon Web Services SDK automatically generates one.
        public let clientToken: String?
        /// If enabled, you can't delete your cluster. You must first disable this property before you can delete your cluster.
        public let deletionProtectionEnabled: Bool?
        /// The KMS key that encrypts and protects the data on your cluster. You can specify the ARN, ID, or alias of an existing key or have Amazon Web Services create a default key for you.
        public let kmsEncryptionKey: String?
        /// The configuration settings when creating a multi-Region cluster, including the witness region and linked cluster properties.
        public let multiRegionProperties: MultiRegionProperties?
        /// A map of key and value pairs to use to tag your cluster.
        public let tags: [String: String]?

        @inlinable
        public init(clientToken: String? = CreateClusterInput.idempotencyToken(), deletionProtectionEnabled: Bool? = nil, kmsEncryptionKey: String? = nil, multiRegionProperties: MultiRegionProperties? = nil, tags: [String: String]? = nil) {
            self.clientToken = clientToken
            self.deletionProtectionEnabled = deletionProtectionEnabled
            self.kmsEncryptionKey = kmsEncryptionKey
            self.multiRegionProperties = multiRegionProperties
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 128)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[!-~]+$")
            try self.validate(self.kmsEncryptionKey, name: "kmsEncryptionKey", parent: name, max: 2048)
            try self.validate(self.kmsEncryptionKey, name: "kmsEncryptionKey", parent: name, min: 1)
            try self.validate(self.kmsEncryptionKey, name: "kmsEncryptionKey", parent: name, pattern: "^[a-zA-Z0-9:/_-]+$")
            try self.multiRegionProperties?.validate(name: "\(name).multiRegionProperties")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[a-zA-Z0-9_.:/=+\\-@ ]*$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[a-zA-Z0-9_.:/=+\\-@ ]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken = "clientToken"
            case deletionProtectionEnabled = "deletionProtectionEnabled"
            case kmsEncryptionKey = "kmsEncryptionKey"
            case multiRegionProperties = "multiRegionProperties"
            case tags = "tags"
        }
    }

    public struct CreateClusterOutput: AWSDecodableShape {
        /// The ARN of the created cluster.
        public let arn: String
        /// The time of when  created the cluster.
        public let creationTime: Date
        /// Whether deletion protection is enabled on this cluster.
        public let deletionProtectionEnabled: Bool
        /// The encryption configuration for the cluster that was specified during the creation process, including the KMS key identifier and encryption state.
        public let encryptionDetails: EncryptionDetails?
        /// The ID of the created cluster.
        public let identifier: String
        /// The multi-Region cluster configuration details that were set during cluster creation
        public let multiRegionProperties: MultiRegionProperties?
        /// The status of the created cluster.
        public let status: ClusterStatus

        @inlinable
        public init(arn: String, creationTime: Date, deletionProtectionEnabled: Bool, encryptionDetails: EncryptionDetails? = nil, identifier: String, multiRegionProperties: MultiRegionProperties? = nil, status: ClusterStatus) {
            self.arn = arn
            self.creationTime = creationTime
            self.deletionProtectionEnabled = deletionProtectionEnabled
            self.encryptionDetails = encryptionDetails
            self.identifier = identifier
            self.multiRegionProperties = multiRegionProperties
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
            case creationTime = "creationTime"
            case deletionProtectionEnabled = "deletionProtectionEnabled"
            case encryptionDetails = "encryptionDetails"
            case identifier = "identifier"
            case multiRegionProperties = "multiRegionProperties"
            case status = "status"
        }
    }

    public struct DeleteClusterInput: AWSEncodableShape {
        /// A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. Idempotency ensures that an API request completes only once. With an idempotent request, if the original request completes successfully. The subsequent retries with the same client token return the result from the original successful request and they have no additional effect. If you don't specify a client token, the Amazon Web Services SDK automatically generates one.
        public let clientToken: String?
        /// The ID of the cluster to delete.
        public let identifier: String

        @inlinable
        public init(clientToken: String? = DeleteClusterInput.idempotencyToken(), identifier: String) {
            self.clientToken = clientToken
            self.identifier = identifier
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.clientToken, key: "client-token")
            request.encodePath(self.identifier, key: "identifier")
        }

        public func validate(name: String) throws {
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 128)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[!-~]+$")
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-z0-9]{26}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteClusterOutput: AWSDecodableShape {
        /// The ARN of the deleted cluster.
        public let arn: String
        /// The time of when the cluster was created.
        public let creationTime: Date
        /// The ID of the deleted cluster.
        public let identifier: String
        /// The status of the cluster.
        public let status: ClusterStatus

        @inlinable
        public init(arn: String, creationTime: Date, identifier: String, status: ClusterStatus) {
            self.arn = arn
            self.creationTime = creationTime
            self.identifier = identifier
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
            case creationTime = "creationTime"
            case identifier = "identifier"
            case status = "status"
        }
    }

    public struct EncryptionDetails: AWSDecodableShape {
        /// The status of encryption for the cluster.
        public let encryptionStatus: EncryptionStatus
        /// The type of encryption that protects the data on your cluster.
        public let encryptionType: EncryptionType
        /// The ARN of the KMS key that encrypts data in the cluster.
        public let kmsKeyArn: String?

        @inlinable
        public init(encryptionStatus: EncryptionStatus, encryptionType: EncryptionType, kmsKeyArn: String? = nil) {
            self.encryptionStatus = encryptionStatus
            self.encryptionType = encryptionType
            self.kmsKeyArn = kmsKeyArn
        }

        private enum CodingKeys: String, CodingKey {
            case encryptionStatus = "encryptionStatus"
            case encryptionType = "encryptionType"
            case kmsKeyArn = "kmsKeyArn"
        }
    }

    public struct GetClusterInput: AWSEncodableShape {
        /// The ID of the cluster to retrieve.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.identifier, key: "identifier")
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-z0-9]{26}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetClusterOutput: AWSDecodableShape {
        /// The ARN of the retrieved cluster.
        public let arn: String
        /// The time of when the cluster was created.
        public let creationTime: Date
        /// Whether deletion protection is enabled in this cluster.
        public let deletionProtectionEnabled: Bool
        /// The current encryption configuration details for the cluster.
        public let encryptionDetails: EncryptionDetails?
        /// The ID of the retrieved cluster.
        public let identifier: String
        /// Returns the current multi-Region cluster configuration, including witness region and linked cluster information.
        public let multiRegionProperties: MultiRegionProperties?
        /// The status of the retrieved cluster.
        public let status: ClusterStatus
        public let tags: [String: String]?

        @inlinable
        public init(arn: String, creationTime: Date, deletionProtectionEnabled: Bool, encryptionDetails: EncryptionDetails? = nil, identifier: String, multiRegionProperties: MultiRegionProperties? = nil, status: ClusterStatus, tags: [String: String]? = nil) {
            self.arn = arn
            self.creationTime = creationTime
            self.deletionProtectionEnabled = deletionProtectionEnabled
            self.encryptionDetails = encryptionDetails
            self.identifier = identifier
            self.multiRegionProperties = multiRegionProperties
            self.status = status
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
            case creationTime = "creationTime"
            case deletionProtectionEnabled = "deletionProtectionEnabled"
            case encryptionDetails = "encryptionDetails"
            case identifier = "identifier"
            case multiRegionProperties = "multiRegionProperties"
            case status = "status"
            case tags = "tags"
        }
    }

    public struct GetVpcEndpointServiceNameInput: AWSEncodableShape {
        /// The ID of the cluster to retrieve.
        public let identifier: String

        @inlinable
        public init(identifier: String) {
            self.identifier = identifier
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.identifier, key: "identifier")
        }

        public func validate(name: String) throws {
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-z0-9]{26}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetVpcEndpointServiceNameOutput: AWSDecodableShape {
        /// The VPC endpoint service name.
        public let serviceName: String

        @inlinable
        public init(serviceName: String) {
            self.serviceName = serviceName
        }

        private enum CodingKeys: String, CodingKey {
            case serviceName = "serviceName"
        }
    }

    public struct InternalServerException: AWSErrorShape {
        public let message: String
        /// Retry after seconds.
        public let retryAfterSeconds: Int?

        @inlinable
        public init(message: String, retryAfterSeconds: Int? = nil) {
            self.message = message
            self.retryAfterSeconds = retryAfterSeconds
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.message = try container.decode(String.self, forKey: .message)
            self.retryAfterSeconds = try response.decodeHeaderIfPresent(Int.self, key: "Retry-After")
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
        }
    }

    public struct ListClustersInput: AWSEncodableShape {
        /// An optional parameter that specifies the maximum number of results to return. You can use nextToken to display the next page of results.
        public let maxResults: Int?
        /// If your initial ListClusters operation returns a nextToken, you can include the returned nextToken in following ListClusters operations, which returns results in the next page.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.maxResults, key: "max-results")
            request.encodeQuery(self.nextToken, key: "next-token")
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListClustersOutput: AWSDecodableShape {
        /// An array of the returned clusters.
        public let clusters: [ClusterSummary]
        /// If nextToken is returned, there are more results available. The value of nextToken is a unique pagination token for each page. To retrieve the next page, make the call again using the returned token.
        public let nextToken: String?

        @inlinable
        public init(clusters: [ClusterSummary], nextToken: String? = nil) {
            self.clusters = clusters
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case clusters = "clusters"
            case nextToken = "nextToken"
        }
    }

    public struct ListTagsForResourceInput: AWSEncodableShape {
        /// The ARN of the resource for which you want to list the tags.
        public let resourceArn: String

        @inlinable
        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 1011)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 1)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:.+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceOutput: AWSDecodableShape {
        /// A map of key and value pairs that you used to tag your resource.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct MultiRegionProperties: AWSEncodableShape & AWSDecodableShape {
        /// The set of linked clusters that form the multi-Region cluster configuration. Each linked cluster represents a database instance in a different  Region.
        public let clusters: [String]?
        /// The  that serves as the witness region for a multi-Region cluster. The witness region helps maintain cluster consistency and quorum.
        public let witnessRegion: String?

        @inlinable
        public init(clusters: [String]? = nil, witnessRegion: String? = nil) {
            self.clusters = clusters
            self.witnessRegion = witnessRegion
        }

        public func validate(name: String) throws {
            try self.clusters?.forEach {
                try validate($0, name: "clusters[]", parent: name, pattern: "^arn:aws(-[^:]+)?:dsql:[a-z0-9-]{1,20}:[0-9]{12}:cluster/[a-z0-9]{26}$")
            }
            try self.validate(self.witnessRegion, name: "witnessRegion", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case clusters = "clusters"
            case witnessRegion = "witnessRegion"
        }
    }

    public struct ResourceNotFoundException: AWSErrorShape {
        public let message: String
        /// The resource ID could not be found.
        public let resourceId: String
        /// The resource type could not be found.
        public let resourceType: String

        @inlinable
        public init(message: String, resourceId: String, resourceType: String) {
            self.message = message
            self.resourceId = resourceId
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case resourceId = "resourceId"
            case resourceType = "resourceType"
        }
    }

    public struct ServiceQuotaExceededException: AWSErrorShape {
        /// The service exception for exceeding a quota.
        public let message: String
        /// The service exceeds a quota.
        public let quotaCode: String
        /// The resource ID exceeds a quota.
        public let resourceId: String
        /// The resource type exceeds a quota.
        public let resourceType: String
        /// The request exceeds a service quota.
        public let serviceCode: String

        @inlinable
        public init(message: String, quotaCode: String, resourceId: String, resourceType: String, serviceCode: String) {
            self.message = message
            self.quotaCode = quotaCode
            self.resourceId = resourceId
            self.resourceType = resourceType
            self.serviceCode = serviceCode
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case quotaCode = "quotaCode"
            case resourceId = "resourceId"
            case resourceType = "resourceType"
            case serviceCode = "serviceCode"
        }
    }

    public struct TagResourceInput: AWSEncodableShape {
        /// The ARN of the resource that you want to tag.
        public let resourceArn: String
        /// A map of key and value pairs to use to tag your resource.
        public let tags: [String: String]

        @inlinable
        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            try container.encode(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 1011)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 1)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:.+$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[a-zA-Z0-9_.:/=+\\-@ ]*$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[a-zA-Z0-9_.:/=+\\-@ ]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct ThrottlingException: AWSErrorShape {
        /// The message that the request was denied due to request throttling.
        public let message: String
        /// The request exceeds a request rate quota.
        public let quotaCode: String?
        /// The request exceeds a request rate quota. Retry after seconds.
        public let retryAfterSeconds: Int?
        /// The request exceeds a service quota.
        public let serviceCode: String?

        @inlinable
        public init(message: String, quotaCode: String? = nil, retryAfterSeconds: Int? = nil, serviceCode: String? = nil) {
            self.message = message
            self.quotaCode = quotaCode
            self.retryAfterSeconds = retryAfterSeconds
            self.serviceCode = serviceCode
        }

        public init(from decoder: Decoder) throws {
            let response = decoder.userInfo[.awsResponse]! as! ResponseDecodingContainer
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.message = try container.decode(String.self, forKey: .message)
            self.quotaCode = try container.decodeIfPresent(String.self, forKey: .quotaCode)
            self.retryAfterSeconds = try response.decodeHeaderIfPresent(Int.self, key: "Retry-After")
            self.serviceCode = try container.decodeIfPresent(String.self, forKey: .serviceCode)
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case quotaCode = "quotaCode"
            case serviceCode = "serviceCode"
        }
    }

    public struct UntagResourceInput: AWSEncodableShape {
        /// The ARN of the resource from which to remove tags.
        public let resourceArn: String
        /// The array of keys of the tags that you want to remove.
        public let tagKeys: [String]

        @inlinable
        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            request.encodeQuery(self.tagKeys, key: "tagKeys")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 1011)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 1)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:.+$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^[a-zA-Z0-9_.:/=+\\-@ ]*$")
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 200)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UpdateClusterInput: AWSEncodableShape {
        /// A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. Idempotency ensures that an API request completes only once. With an idempotent request, if the original request completes successfully. The subsequent retries with the same client token return the result from the original successful request and they have no additional effect. If you don't specify a client token, the Amazon Web Services SDK automatically generates one.
        public let clientToken: String?
        /// Specifies whether to enable deletion protection in your cluster.
        public let deletionProtectionEnabled: Bool?
        /// The ID of the cluster you want to update.
        public let identifier: String
        /// The KMS key that encrypts and protects the data on your cluster. You can specify the ARN, ID, or alias of an existing key or have Amazon Web Services create a default key for you.
        public let kmsEncryptionKey: String?
        /// The new multi-Region cluster configuration settings to be applied during an update operation.
        public let multiRegionProperties: MultiRegionProperties?

        @inlinable
        public init(clientToken: String? = UpdateClusterInput.idempotencyToken(), deletionProtectionEnabled: Bool? = nil, identifier: String, kmsEncryptionKey: String? = nil, multiRegionProperties: MultiRegionProperties? = nil) {
            self.clientToken = clientToken
            self.deletionProtectionEnabled = deletionProtectionEnabled
            self.identifier = identifier
            self.kmsEncryptionKey = kmsEncryptionKey
            self.multiRegionProperties = multiRegionProperties
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encodeIfPresent(self.clientToken, forKey: .clientToken)
            try container.encodeIfPresent(self.deletionProtectionEnabled, forKey: .deletionProtectionEnabled)
            request.encodePath(self.identifier, key: "identifier")
            try container.encodeIfPresent(self.kmsEncryptionKey, forKey: .kmsEncryptionKey)
            try container.encodeIfPresent(self.multiRegionProperties, forKey: .multiRegionProperties)
        }

        public func validate(name: String) throws {
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 128)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[!-~]+$")
            try self.validate(self.identifier, name: "identifier", parent: name, pattern: "^[a-z0-9]{26}$")
            try self.validate(self.kmsEncryptionKey, name: "kmsEncryptionKey", parent: name, max: 2048)
            try self.validate(self.kmsEncryptionKey, name: "kmsEncryptionKey", parent: name, min: 1)
            try self.validate(self.kmsEncryptionKey, name: "kmsEncryptionKey", parent: name, pattern: "^[a-zA-Z0-9:/_-]+$")
            try self.multiRegionProperties?.validate(name: "\(name).multiRegionProperties")
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken = "clientToken"
            case deletionProtectionEnabled = "deletionProtectionEnabled"
            case kmsEncryptionKey = "kmsEncryptionKey"
            case multiRegionProperties = "multiRegionProperties"
        }
    }

    public struct UpdateClusterOutput: AWSDecodableShape {
        /// The ARN of the updated cluster.
        public let arn: String
        /// The time of when the cluster was created.
        public let creationTime: Date
        /// The ID of the cluster to update.
        public let identifier: String
        /// The status of the updated cluster.
        public let status: ClusterStatus

        @inlinable
        public init(arn: String, creationTime: Date, identifier: String, status: ClusterStatus) {
            self.arn = arn
            self.creationTime = creationTime
            self.identifier = identifier
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "arn"
            case creationTime = "creationTime"
            case identifier = "identifier"
            case status = "status"
        }
    }

    public struct ValidationException: AWSErrorShape {
        /// A list of fields that didn't validate.
        public let fieldList: [ValidationExceptionField]?
        public let message: String
        /// The reason for the validation exception.
        public let reason: ValidationExceptionReason

        @inlinable
        public init(fieldList: [ValidationExceptionField]? = nil, message: String, reason: ValidationExceptionReason) {
            self.fieldList = fieldList
            self.message = message
            self.reason = reason
        }

        private enum CodingKeys: String, CodingKey {
            case fieldList = "fieldList"
            case message = "message"
            case reason = "reason"
        }
    }

    public struct ValidationExceptionField: AWSDecodableShape {
        /// A message describing why this field failed validation.
        public let message: String
        /// The name of the field.
        public let name: String

        @inlinable
        public init(message: String, name: String) {
            self.message = message
            self.name = name
        }

        private enum CodingKeys: String, CodingKey {
            case message = "message"
            case name = "name"
        }
    }
}

// MARK: - Errors

/// Error enum for DSQL
public struct DSQLErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize DSQL
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// You do not have sufficient access to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// The submitted action has conflicts.
    public static var conflictException: Self { .init(.conflictException) }
    /// The request processing has failed because of an unknown error, exception or failure.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The resource could not be found.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// The service limit was exceeded.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The request was denied due to request throttling.
    public static var throttlingException: Self { .init(.throttlingException) }
    /// The input failed to satisfy the constraints specified by an Amazon Web Services service.
    public static var validationException: Self { .init(.validationException) }
}

extension DSQLErrorType: AWSServiceErrorType {
    public static let errorCodeMap: [String: AWSErrorShape.Type] = [
        "ConflictException": DSQL.ConflictException.self,
        "InternalServerException": DSQL.InternalServerException.self,
        "ResourceNotFoundException": DSQL.ResourceNotFoundException.self,
        "ServiceQuotaExceededException": DSQL.ServiceQuotaExceededException.self,
        "ThrottlingException": DSQL.ThrottlingException.self,
        "ValidationException": DSQL.ValidationException.self
    ]
}

extension DSQLErrorType: Equatable {
    public static func == (lhs: DSQLErrorType, rhs: DSQLErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension DSQLErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
